﻿#region License
/*

	Copyright (C) 2008 Oliver Charles, Daniel Hollander

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
	
*/
#endregion

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Xml;
using Moebius.Core;

namespace Moebius.Rendering
{
    /// <summary>
    /// An image atlus is a set of images that have been collected together into one larger image. This increases efficiency as
    /// it means that less texture changes are required.
    /// </summary>
    public sealed class ImageAtlas
    {
        private readonly Dictionary<string, RectangleF> imageRegions = new Dictionary<string, RectangleF>();
        private ITexture texture;

        public ITexture Texture
        {
            get { return texture; }
            internal set { texture = value; }
        }
        #region Constructors

        internal ImageAtlas() {}

        #endregion

        #region Activate

        /// <summary>
        /// Activates this Image Atlus on the rendering device.
        /// </summary>
        public void Activate()
        {
            Texture.Activate();
        }

        #endregion

        #region Get UV Coordinates

        /// <summary>
        /// Get the UV coordinates of an image in the image atlus.
        /// </summary>
        /// <param name="identifier">The name of the image to locate</param>
        /// <returns>A <see cref="RectangleF"/> instance, representing the UV region.</returns>
        public RectangleF GetUVCoordinates(string identifier)
        {
            if(!imageRegions.ContainsKey(identifier))
                throw new ArgumentException("Image atlas does not contain the specified image", identifier);

            float uScale = 1.0f / Texture.Width;
            float vScale = 1.0f / Texture.Height;

            RectangleF region = imageRegions[identifier];
            RectangleF uvCoords = new RectangleF(region.Left * uScale, region.Top * vScale,
                region.Width * uScale, region.Height * vScale);

            return uvCoords;
        }

        #endregion

        #region Add Image Region

        public void AddImageRegion(string name, RectangleF region)
        {
            imageRegions.Add(name, region);
        }

        #endregion
    }

    public class ImageAtlasResourceManager : ResourceManager
    {
        public override object LoadResource(string fileName, ResourceFactory resources)
        {
            ImageAtlas atlus = new ImageAtlas();

            XmlDocument atlasDocument = new XmlDocument();
            atlasDocument.Load(fileName);

            XmlNode imageSet = atlasDocument.SelectSingleNode("/imageSet");
            atlus.Texture = resources.Load<ITexture>(imageSet.Attributes["atlus"].Value.Trim());

            XmlNodeList images = imageSet.SelectNodes("image");

            foreach (XmlNode image in images)
            {
                string identifier = image.Attributes["identifier"].Value.Trim();

                XmlNode origin = image.SelectSingleNode("origin");
                float x = float.Parse(origin.Attributes["x"].Value.Trim(), CultureInfo.GetCultureInfo("en-gb"));
                float y = float.Parse(origin.Attributes["y"].Value.Trim(), CultureInfo.GetCultureInfo("en-gb"));

                XmlNode size = image.SelectSingleNode("size");
                float width = float.Parse(size.Attributes["width"].Value.Trim(), CultureInfo.GetCultureInfo("en-gb"));
                float height = float.Parse(size.Attributes["height"].Value.Trim(), CultureInfo.GetCultureInfo("en-gb"));

                atlus.AddImageRegion(identifier, new RectangleF(x, y, width, height));
            }

            return atlus;
        }
    }
}
